function AtomicModels(graphics) {
  this.type = "atomic_models";
  var opts = graphics.options;
  if (opts && opts.atoms && opts.labels) {
    if (!opts.charges) {
      opts.charges = [];
    }
    for (var i = 0; i < opts.atoms.length; i++) {
      if (!opts.charges[i]) {
        opts.charges[i] = "0";
      }
    }
    this.options = opts;
  } else {
    this.options = { atoms : ["C-12"], charges : ["0"], labels : [] };
  }
}

AtomicModels.prototype = {
  edit : function() {
    this.show($("#item .content"));
    this.showOptions();
  },

  showOptions : function() {
    Graphics.prototype.showOptions.apply(this, arguments);
    this.showAtomOptions();
    this.showLabelOptions();
  },

  show : function(target) {
    if (target == null) { target = $("#item .content"); }
    target.html("<table class='atomic_models' style='width:100%; height:100%'>" +
      "<tr class='models'></tr><tr class='labels'></tr></table>");
    var models = target.find(".models");
    var labels = target.find(".labels");
    var atoms = this.options.atoms;
    var charges = this.options.charges;
    var n = atoms.length;
    var scale = 0.3 * (n < 3 ? 400 : (n == 3 ? 360 : 320));
    var width = n < 3 ? 360 : 280;
    var height = width;
    for (var i = 0; i < n; i++) {
      var atom = i2a(atoms[i]);
      models.append("<td id='isotope-" + i + "' class='" + (n == 1 ? "a-right" : "a-center") + " a-middle'>" +
        "<canvas width='" + width + "px' height='" + height + "px'></canvas></div>");
      var canvas = models.find("#isotope-" + i + " canvas")[0];
      atom.drawAtomicModel(canvas.getContext("2d"), 0.5 * width, 0.5 * width, scale, { charge : charges[i] } );
      var label = "";
      for (var j = 0; j < this.options.labels.length; j++) {
        var text = "";
        switch(this.options.labels[j]) {
          case "element" :
            text = atom["name"];
            break;
          case "isotope" :
            text = atom["name"] + "-" + atom["mass"];
            break;
          case "protons" :
            text = "# of protons = " + atom["protons"];
            break;
          case "neutrons" :
            text = "# of neutrons = " + atom["neutrons"];
            break;
          case "number" :
            text = "atomic number = " + atom["protons"];
            break;
          case "mass" :
            text = "atomic mass = " + atom["mass"] + " amu";
            break;
          case "charge" :
            var c = charges[i].trim();
            text = "charge = " + (c > 0 ? "+" : "") + c;
            break;
        }
        label += (j == 0 ? "<td class='a-center' style='font-size: 24px;'>" : "") + text +
          ((j + 1 == this.options.labels.length) ? "</td>" : "<br />");
      }
      labels.append(label);
    }
    if (n < 3) {
      models.append("<td class='a-center' style='width:" + (n == 1 ? 2.8 : 2) * scale + "px'>" +
        "<canvas id='legend' class='a-center a-middle' " +
        "width='" + 1.5 * scale + "px' height='" + 1.6 * scale + "'></canvas></td>");
      models.legend = models.find("canvas#legend");
      models.legend.css( {
        "border" : "1px solid #bbb", "border-radius" : "12px", "-moz-border-radius" : "12px",
        "box-shadow" : "2px 2px 4px 4px rgba(0, 0, 0, 0.08)" }
      );
      var ctx = models.legend[0].getContext("2d");
      i2a("H-1").drawVerticalLegend(ctx, 0.5 * ctx.canvas.width, 0.5 * ctx.canvas.height, scale);
    }
  },

  showAtomOptions : function() {
    if ($("#item .options .atoms").length == 0) {
      $("#item .options").append("<div class='atoms'></div>");
    }
    var atoms = $("#item .options .atoms");
    var n = this.options.atoms.length;
    atoms.html("Atom" + (n != 1 ? "s" : "") + " :");
    for (var i = 0; i < n; i++) {
      atoms.append("<span class='isotope-" + i + "'></span>");
      var atom = atoms.find(".isotope-" + i);
      atom.append("<select class='isotope-" + i + "'></select>");
      for (var j in i2n) {
        atom.find("select").append("<option value='" + j + "'" +
          (j == this.options.atoms[i] ? " selected='selected'" : "") + ">" +
          i2n[j] + "</option>");
      }
      atoms.find(".isotope-" + i + " select").change(function() {
        var item = lesson.items.current;
        var ix = this.className.substring(this.className.length - 1);
        item.graphics.options.atoms[ix] = this.value;
        item.graphics.show();
        item.saveProperty("graphics", JSON.stringify(item.graphics));
      });

      atoms.append("<span class='charge-" + i +"'></span>");
      var charge = atoms.find(".charge-" + i);
      charge.append("<select class='charge-" + i + "'></select");
      for (var k = -2; k <= 2; k++) {
        charge.find("select").append("<option value='" + k + "'" +
          (k == this.options.charges[i] ? " selected='selected'" : "") + ">" +
          (k > 0 ? "+" : "") + k + "</option>");
      }
      atoms.find(".charge-" + i + " select").change(function() {
        var item = lesson.items.current;
        var ix = this.className.substring(this.className.length - 1);
        if (!item.graphics.options.charges) {
          item.graphics.options.charges = [];
        }
        item.graphics.options.charges[ix] = this.value;
        item.graphics.show();
        item.saveProperty("graphics", JSON.stringify(item.graphics));
      });
    }
    atoms.append("<span><a class='add-atom'>add</a></span>" +
      "<span><a class='remove-atom'>remove</a></span>");
    atoms.find("a.add-atom, a.remove-atom").click(function() {
      var item = lesson.items.current;
      if (this.className == "add-atom") {
        item.graphics.options.atoms.push("H-1");
        item.graphics.options.charges.push("0");
      }
      else if (this.className == "remove-atom") {
        item.graphics.options.atoms.pop();
        item.graphics.options.charges.pop();
      }
      item.saveProperty("graphics", JSON.stringify({
        type : item.graphics.type, options : item.graphics.options
      }));
      item.graphics.show();
      item.graphics.showAtomOptions();
    });
    atoms.find("span").css( { "margin" : "0 4px" } );
  },

  showLabelOptions : function() {
    if ($("#item .options .labels").length == 0) {
      $("#item .options").append("<div class='labels' style='margin-top:8px;'></div>");
    }
    var labels = $("#item .options .labels").html("<hr />Labels : ");
    var values = ["element", "isotope", "protons", "neutrons", "number", "mass", "charge"];
    var text = ["element name", "isotope name", "# of protons", "# of neutrons", "atomic number", "atomic mass", "charge"];
    for (var j = 0 ; j < values.length; j++) {
      labels.append("<input type='checkbox' value='" + values[j] + "' /><span>" + text[j] + "</span>");
    }
    labels.inputs = labels.find("input");
    labels.inputs.css( { "zoom" : "120%", "position" : "relative", "bottom" : "1px", "margin" : "0 4px" } );
    labels.find("span").css( { "position" : "relative", "top" : "1px", "padding" : "0 48px 0 8px" } );
    for (var i = 0; i < labels.inputs.length; i++) {
      var input = $(labels.inputs[i]);
      if ($.inArray(input.val(), lesson.items.current.graphics.options.labels) > -1) {
        input.attr("checked", true);
      }
    }
    labels.inputs.change(function() {
      var item = lesson.items.current;
      var labels = item.graphics.options.labels;
      var ix = $.inArray(this.value, labels);
      if ($(this).prop("checked") && ix < 0) {
        item.graphics.options.labels.push(this.value);
      } else if (!$(this).prop("checked") && ix >= 0) {
        item.graphics.options.labels = [];
        for (var i = 0; i < labels.length; i++) {
          if (labels[i] != this.value) { item.graphics.options.labels.push(labels[i]); }
        }
      }
      item.saveProperty("graphics", JSON.stringify(
        { type : item.graphics.type, options : item.graphics.options } ));
      item.graphics.show();
    })
  }
};